home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Deutsche Edition 2
/
Deutsche Edition 2.iso
/
mac
/
POWERMAC
/
C64
/
SOURCE
/
Processor.c
< prev
next >
Wrap
Text File
|
1994-06-06
|
8KB
|
378 lines
/*
Commodore 64 Emulator v0.4 Earle F. Philhower III
Copyright (C) 1993-4 (st916w9r@dunx1.ocs.drexel.edu)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <AppleEvents.h>
#include "Processor.h"
#include "Modes.h"
#include "Stack.h"
#include "Keyboard.h"
#include "Resources.h"
#include "Preferences.h"
extern Cursor commieCursor;
extern void (* instruct[256]) ();
extern byte cycletime[256];
extern int programMode;
byte interruptProcessor;
static byte numLeftSameChar;
static void ProcessPerLine(void);
extern void ProcessorLoop(void);
void CProcessorLoop(), M68kProcessorLoop(), IntProcessorLoop();
void ProcessorLoop()
{
switch (globalPref.useProcessor)
{
case asmProcessor:
#ifndef __MWERKS__
M68kProcessorLoop();
#else
IntProcessorLoop();
#endif
break;
case cProcessor:
CProcessorLoop();
break;
case intCProcessor:
IntProcessorLoop();
break;
}
}
void CProcessorLoop()
{
int scanLines, vicCalls;
byte instructCode, oldMemoryMap, processorCycles, col;
Str255 str;
programMode=kRunning;
ShowVICWindow();
/* Set up window, cursor for running state */
GetIndString(str, kWindowStrings, kRunningWindow);
SetVICTitle(str);
SetCursor(&commieCursor);
ObscureCursor();
/* Set up the memory dereferences, and store current map */
oldMemoryMap=*RAMp1;
SetUpMemoryMap();
/* Some flags and counters necessray to be initialized */
interruptProcessor=0;
numLeftSameChar=0;
processorCycles=0;
scanLines=0;
vicCalls=0;
while (interruptProcessor==0)
{
instructCode = ImmediateByte(); pc++;
processorCycles += cycletime[instructCode];
(*instruct[instructCode])();
/* Set up the memory map if it has changed */
if (*RAMp1!=oldMemoryMap)
{
SetUpMemoryMap();
oldMemoryMap=*RAMp1;
}
/* If we've done 35 cycles, we've gone through 1 scanline */
if (processorCycles>35)
{
processorCycles=0;
/* Update the current VIC scan register */
if (++RAM[0xd012]==0) RAM[0xd011] ^= 128;
RAM[0xd018] |=1;
/* If we've gone through 350 lines, we've due for an interrupt */
if (++scanLines>350)
{
scanLines=0;
/* Set raster to 0 line */
RAM[0xd012]=0;
RAM[0xd011]&=127;
/* Currently we just update the keyboard registers */
ProcessPerLine();
if (++vicCalls==2)
{
RedrawVIC();
vicCalls=0;
}
/* Call interrupt routine if interrupts enabled */
if ((flags&INT)==0)
{
PushWord(pc);
Push(flags);
pc=WordAt(IrqTo);
}
}
}
/* Set up the keyboard register according to precomputed values */
RAM[0xdc01]=scanCode[RAM[0xdc00]];
}
/* Done processing, reset window, cursor */
RedrawVIC();
SetCursor(&qd.arrow);
GetIndString(str, kWindowStrings, kSuspendedWindow);
SetVICTitle(str);
programMode=kSleeping;
}
extern void CPU(void);
void M68kProcessorLoop()
{
#ifndef __MWERKS__
int vicCalls;
byte *d012, *d011, *d018;
Str255 str;
ShowVICWindow();
/* Set up window, cursor for running state */
GetIndString(str, kWindowStrings, kRunningWindow);
SetVICTitle(str);
SetCursor(&commieCursor);
ObscureCursor();
/* Initialize precomputed addresses (minimal speed gain) */
d012=&RAM[0xd012];
d011=&RAM[0xd011];
d018=&RAM[0xd018];
/* Store current map */
SetUpMemoryMap();
/* Some flags and counters necessary to be initialized */
interruptProcessor=0;
numLeftSameChar=0;
vicCalls=0;
while (interruptProcessor==0) {
/* Most of the functionality of the CPU has been moved to this function.
* This function will execute for 350 screen lines.
*/
CPU();
/* If we've gone through 350 lines, we've due for an interrupt */
/* Set raster to 0 line */
*d012=0;
*d011&=127;
/* Currently we just update the keyboard registers */
ProcessPerLine();
if (++vicCalls==2)
{
RedrawVIC();
vicCalls=0;
}
/* Call interrupt routine if interrupts enabled */
if ((flags&INT)==0)
{
PushWord(pc);
Push(flags);
pc=WordAt(IrqTo);
}
}
/* Done processing, reset window, cursor */
RedrawVIC();
SetCursor(&qd.arrow);
GetIndString(str, kWindowStrings, kSuspendedWindow);
SetVICTitle(str);
#endif
}
/* Called once per scanline, currently check for keypress or mouse button */
static void ProcessPerLine()
{
EventRecord evt;
WindowPtr theWind;
int x;
char theChar;
/* We keep the same keyboard map for 1/30th of a second */
if (numLeftSameChar==0)
{
numLeftSameChar=2;
/* Check for any key or mouse press */
if (GetNextEvent(-1, &evt)!=false)
switch(evt.what)
{
case mouseDown:
/* A mouseclick stops our simulation */
MiniHandleMouseDown(evt);
break;
case updateEvt:
theWind=(WindowPtr)evt.message;
BeginUpdate(theWind);
switch (GetWRefCon(theWind))
{
case kVICWindow:
break;
case kDirWindow:
RedrawDir();
break;
case kAboutWindow:
break;
}
EndUpdate(theWind);
break;
case app4Evt:
if ((evt.message&1)==0) interruptProcessor=1;
break;
case kHighLevelEvent:
AEProcessAppleEvent(&evt);
break;
case keyDown:
case autoKey:
/* A keypress is simulated by fudging the CIA registers */
theChar = evt.message&charCodeMask;
if ((evt.modifiers&cmdKey)!=0) DoMenuChoice(MenuKey(theChar));
else AppleScanKeyboard(evt.message&charCodeMask, evt.modifiers);
}
/* No keypress, so clear out keyboard register fudge */
else
{
for (x=0; x<256; x++) scanCode[x]=0xff;
SystemTask();
}
}
else numLeftSameChar--;
}
MiniHandleMouseDown(event)
EventRecord event;
{
WindowPtr theWind;
GrafPtr gp;
Point x;
short thePart;
extern Rect dragRect;
thePart=FindWindow(event.where, &theWind);
switch(thePart)
{
case inSysWindow:
SystemClick(&event, theWind);
interruptProcessor=1;
break;
case inDrag:
if (GetWRefCon(theWind)==kVICWindow) DragVICWindow(&event);
else DragWindow(theWind, event.where, &dragRect);
break;
case inMenuBar:
DoMenuChoice(MenuSelect(event.where));
break;
case inContent:
SelectWindow(theWind);
interruptProcessor=1;
break;
}
}
void IntProcessorLoop()
{
int vicCalls;
byte *d012, *d011, *d018;
Str255 str;
ShowVICWindow();
/* Set up window, cursor for running state */
GetIndString(str, kWindowStrings, kRunningWindow);
SetVICTitle(str);
SetCursor(&commieCursor);
ObscureCursor();
/* Initialize precomputed addresses (minimal speed gain) */
d012=&RAM[0xd012];
d011=&RAM[0xd011];
d018=&RAM[0xd018];
/* Store current map */
SetUpMemoryMap();
/* Some flags and counters necessary to be initialized */
interruptProcessor=0;
numLeftSameChar=0;
vicCalls=0;
while (interruptProcessor==0) {
/* Most of the functionality of the CPU has been moved to this function.
* This function will execute for 350 screen lines.
*/
IntegratedProcessor(&a, &x, &y, &flags, &sp, &pc, memory, RAM);
/* If we've gone through 350 lines, we've due for an interrupt */
/* Set raster to 0 line */
*d012=0;
*d011&=127;
/* Currently we just update the keyboard registers */
ProcessPerLine();
if (++vicCalls==2)
{
RedrawVIC();
vicCalls=0;
}
/* Call interrupt routine if interrupts enabled */
if ((flags&INT)==0)
{
PushWord(pc);
Push(flags);
pc=WordAt(IrqTo);
}
}
/* Done processing, reset window, cursor */
RedrawVIC();
SetCursor(&qd.arrow);
GetIndString(str, kWindowStrings, kSuspendedWindow);
SetVICTitle(str);
}